@@ -95,8 +95,6 @@ module Agents |
||
95 | 95 |
] |
96 | 96 |
end |
97 | 97 |
|
98 |
- after_save :clear_matchers |
|
99 |
- |
|
100 | 98 |
def validate_options |
101 | 99 |
errors.add(:base, "instructions and mode need to be present.") unless options['instructions'].present? && options['mode'].present? |
102 | 100 |
|
@@ -120,12 +118,15 @@ module Agents |
||
120 | 118 |
end |
121 | 119 |
|
122 | 120 |
def receive(incoming_events) |
121 |
+ matchers = compiled_matchers |
|
122 |
+ |
|
123 | 123 |
incoming_events.each do |event| |
124 | 124 |
interpolate_with(event) do |
125 |
- interpolation_context.merge(perform_matching(event.payload)) |
|
126 |
- formatted_event = interpolated['mode'].to_s == "merge" ? event.payload.dup : {} |
|
127 |
- formatted_event.merge! interpolated['instructions'] |
|
128 |
- create_event :payload => formatted_event |
|
125 |
+ apply_compiled_matchers(matchers, event) do |
|
126 |
+ formatted_event = interpolated['mode'].to_s == "merge" ? event.payload.dup : {} |
|
127 |
+ formatted_event.merge! interpolated['instructions'] |
|
128 |
+ create_event payload: formatted_event |
|
129 |
+ end |
|
129 | 130 |
end |
130 | 131 |
end |
131 | 132 |
end |
@@ -164,49 +165,47 @@ module Agents |
||
164 | 165 |
end |
165 | 166 |
end |
166 | 167 |
|
167 |
- def perform_matching(payload) |
|
168 |
- matchers.inject(payload.dup) { |hash, matcher| |
|
169 |
- matcher[hash] |
|
170 |
- } |
|
168 |
+ def compiled_matchers |
|
169 |
+ if matchers = options['matchers'] |
|
170 |
+ matchers.map { |matcher| |
|
171 |
+ regexp, path, to = matcher.values_at(*%w[regexp path to]) |
|
172 |
+ [Regexp.new(regexp), path, to] |
|
173 |
+ } |
|
174 |
+ end |
|
171 | 175 |
end |
172 | 176 |
|
173 |
- def matchers |
|
174 |
- @matchers ||= |
|
175 |
- if matchers = options['matchers'] |
|
176 |
- matchers.map { |matcher| |
|
177 |
- regexp, path, to = matcher.values_at(*%w[regexp path to]) |
|
178 |
- re = Regexp.new(regexp) |
|
179 |
- proc { |hash| |
|
180 |
- mhash = {} |
|
181 |
- value = interpolate_string(path, hash) |
|
182 |
- if value.is_a?(String) && (m = re.match(value)) |
|
183 |
- m.to_a.each_with_index { |s, i| |
|
184 |
- mhash[i.to_s] = s |
|
185 |
- } |
|
186 |
- m.names.each do |name| |
|
187 |
- mhash[name] = m[name] |
|
188 |
- end if m.respond_to?(:names) |
|
189 |
- end |
|
190 |
- if to |
|
191 |
- case value = hash[to] |
|
192 |
- when Hash |
|
193 |
- value.update(mhash) |
|
194 |
- else |
|
195 |
- hash[to] = mhash |
|
196 |
- end |
|
197 |
- else |
|
198 |
- hash.update(mhash) |
|
199 |
- end |
|
200 |
- hash |
|
201 |
- } |
|
202 |
- } |
|
203 |
- else |
|
204 |
- [] |
|
177 |
+ def apply_compiled_matchers(matchers, event, &block) |
|
178 |
+ return yield if matchers.nil? |
|
179 |
+ |
|
180 |
+ # event.payload.dup does not work; HashWithIndifferentAccess is |
|
181 |
+ # a source of trouble here. |
|
182 |
+ hash = {}.update(event.payload) |
|
183 |
+ |
|
184 |
+ matchers.each do |re, path, to| |
|
185 |
+ m = re.match(interpolate_string(path, hash)) or next |
|
186 |
+ |
|
187 |
+ mhash = |
|
188 |
+ if to |
|
189 |
+ case value = hash[to] |
|
190 |
+ when Hash |
|
191 |
+ value |
|
192 |
+ else |
|
193 |
+ hash[to] = {} |
|
194 |
+ end |
|
195 |
+ else |
|
196 |
+ hash |
|
197 |
+ end |
|
198 |
+ |
|
199 |
+ m.size.times do |i| |
|
200 |
+ mhash[i.to_s] = m[i] |
|
205 | 201 |
end |
206 |
- end |
|
207 | 202 |
|
208 |
- def clear_matchers |
|
209 |
- @matchers = nil |
|
203 |
+ m.names.each do |name| |
|
204 |
+ mhash[name] = m[name] |
|
205 |
+ end |
|
206 |
+ end |
|
207 |
+ |
|
208 |
+ interpolate_with(hash, &block) |
|
210 | 209 |
end |
211 | 210 |
end |
212 | 211 |
end |
@@ -8,6 +8,7 @@ describe Agents::EventFormattingAgent do |
||
8 | 8 |
:instructions => { |
9 | 9 |
:message => "Received {{content.text}} from {{content.name}} .", |
10 | 10 |
:subject => "Weather looks like {{conditions}} according to the forecast at {{pretty_date.time}}", |
11 |
+ :timezone => "{{timezone}}", |
|
11 | 12 |
:agent => "{{agent.type}}", |
12 | 13 |
:created_at => "{{created_at}}", |
13 | 14 |
:created_at_iso => "{{created_at | date:'%FT%T%:z'}}", |
@@ -19,6 +20,10 @@ describe Agents::EventFormattingAgent do |
||
19 | 20 |
:regexp => "\\A(?<time>\\d\\d:\\d\\d [AP]M [A-Z]+)", |
20 | 21 |
:to => "pretty_date", |
21 | 22 |
}, |
23 |
+ { |
|
24 |
+ :path => "{{pretty_date.time}}", |
|
25 |
+ :regexp => "(?<timezone>[A-Z]+)\\z", |
|
26 |
+ }, |
|
22 | 27 |
], |
23 | 28 |
} |
24 | 29 |
} |
@@ -50,8 +55,8 @@ describe Agents::EventFormattingAgent do |
||
50 | 55 |
:name => "somevalue2", |
51 | 56 |
}, |
52 | 57 |
:date => { |
53 |
- :epoch => "1357966800", |
|
54 |
- :pretty => "00:00 AM EST on January 12, 2015" |
|
58 |
+ :epoch => "1366372800", |
|
59 |
+ :pretty => "08:00 AM EDT on April 19, 2013" |
|
55 | 60 |
}, |
56 | 61 |
:conditions => "someothervalue2" |
57 | 62 |
} |
@@ -85,7 +90,24 @@ describe Agents::EventFormattingAgent do |
||
85 | 90 |
formatted_event1, formatted_event2 = Event.last(2) |
86 | 91 |
|
87 | 92 |
expect(formatted_event1.payload[:subject]).to eq("Weather looks like someothervalue according to the forecast at 10:00 PM EST") |
88 |
- expect(formatted_event2.payload[:subject]).to eq("Weather looks like someothervalue2 according to the forecast at 00:00 AM EST") |
|
93 |
+ expect(formatted_event1.payload[:timezone]).to eq("EST") |
|
94 |
+ expect(formatted_event2.payload[:subject]).to eq("Weather looks like someothervalue2 according to the forecast at 08:00 AM EDT") |
|
95 |
+ expect(formatted_event2.payload[:timezone]).to eq("EDT") |
|
96 |
+ end |
|
97 |
+ |
|
98 |
+ it "should not fail if no matchers are defined" do |
|
99 |
+ @checker.options.delete(:matchers) |
|
100 |
+ |
|
101 |
+ expect { |
|
102 |
+ @checker.receive([@event, @event2]) |
|
103 |
+ }.to change { Event.count }.by(2) |
|
104 |
+ |
|
105 |
+ formatted_event1, formatted_event2 = Event.last(2) |
|
106 |
+ |
|
107 |
+ expect(formatted_event1.payload[:subject]).to eq("Weather looks like someothervalue according to the forecast at ") |
|
108 |
+ expect(formatted_event1.payload[:timezone]).to eq("") |
|
109 |
+ expect(formatted_event2.payload[:subject]).to eq("Weather looks like someothervalue2 according to the forecast at ") |
|
110 |
+ expect(formatted_event2.payload[:timezone]).to eq("") |
|
89 | 111 |
end |
90 | 112 |
|
91 | 113 |
it "should allow escaping" do |